package jsr292.java.lang.invoke;

import java.lang.reflect.Field;

import jsr292.weaver.Capabilities;
import jsr292.weaver.Debug;
import jsr292.weaver.opt.OptimizerContext;
import jsr292.weaver.opt.OptimizerSnippets;
import jsr292.weaver.opt.OptimizerVarAllocator;

class MHLookupUnreflectSetter extends MethodHandle {
    private final Field field;
    
    public MHLookupUnreflectSetter(Field field, MethodType methodType) {
        super(methodType);
        this.field=field;
    }

    private Object invoke(Object target, Object value) {
        try {
            field.set(target, value);
        } catch (IllegalAccessException e) {
            throw (LinkageError)new LinkageError().initCause(e);
        }
        return null;
    }
    
    @Override
    public Object $invoke$(Object o1) {
        return invoke(null, o1);
    }
    
    @Override
    public Object $invoke$(Object o1, Object o2) {
        return invoke(o1, o2);
    }
    
    @Override
    public boolean isWeavable(Class<?> classBeingRedefined) {
        if (!Access.isVisible(classBeingRedefined, field) && !Capabilities.canUseUnsafe()) {
            if (Debug.DEBUG) System.err.println("unreflect setter field: can't access to "+field+" and unsafe not available");
            return false;
        }
        return true;
    }
    @Override
    public void weave(OptimizerContext context, OptimizerVarAllocator allocator) {
        if (Debug.DEBUG) {
            Debug.checkAllocator(allocator, this);
        }
        
        OptimizerSnippets.unreflectSetter(context, allocator, field);
    }
}
